const { expect, use } = require("chai")
const { ethers } = require("hardhat")

describe("AdvancedDeFi - 单个用户存款测试", function () {
    // 全局变量定义
    let advancedDeFi // 合约实例
    let gameToken // 存款代币实例
    let owner, user // 测试账户
    const depositAmount = ethers.parseEther("100") // 存款数量（100个代币）

    /**
     * 前置操作：部署合约并准备测试环境
     */
    before(async function () {
        // 获取测试账户
        ;[owner, user] = await ethers.getSigners()

        // 1. 部署测试代币（GameToken）
        const Token = await ethers.getContractFactory("GameToken")
        gameToken = await Token.deploy()
        await gameToken.waitForDeployment()
        const gameTokenAddress = await gameToken.getAddress()
        console.log("GameToken 部署地址:", gameTokenAddress)

        //2.部署Defi合约
        const AdvancedDeFi = await ethers.getContractFactory("AdvancedDeFi")
        advancedDeFi = await AdvancedDeFi.deploy(gameTokenAddress)
        await advancedDeFi.waitForDeployment()
        const defiAddress = await advancedDeFi.getAddress()
        console.log("AdvancedDeFi 部署地址:", defiAddress)

        // 3. 给用户转账测试代币（用于存款）
        await gameToken.transfer(user.address, depositAmount)
        const userInitialBalance = await gameToken.balanceOf(user.address)
        console.log("用户初始代币余额:", ethers.formatEther(userInitialBalance))
    })
    /**
     * 核心测试用例：单个用户存款功能验证
     */
    it("despoite 存款", async function () {
        // 切换到用户上下文
        const userToken = gameToken.connect(user) //用户合约代币
        const userDefi = advancedDeFi.connect(user) //用户defi合约
        const defiAddress = await advancedDeFi.getAddress()
        //1.授权合约使用用户代币
        await userToken.approve(defiAddress, depositAmount)
        console.log("已授权合约使用用户代币")

        //记录存款钱的状态
        const userBalanceBefore = await userToken.balanceOf(user.address)
        const contractBalanceBefore = await userToken.balanceOf(defiAddress)

        //执行存款操作
        const depositTx = await userDefi.deposit(depositAmount)
        await depositTx.wait() //等待交易链上确认
        console.log("存款交易已确认")
        // 4. 验证存款事件
        await expect(depositTx)
            .to.emit(advancedDeFi, "Deposited")
            .withArgs(user.address, depositAmount, await getBlockTimestamp())

        // 5. 验证余额变化
        // 5.1 用户余额应减少存款金额
        const userBalanceAfter = await userToken.balanceOf(user.address)
        expect(userBalanceAfter).to.equal(userBalanceBefore - depositAmount)

        // 5.2 合约余额应增加存款金额
        const contractBalanceAfter = await userToken.balanceOf(defiAddress)
        expect(contractBalanceAfter).to.equal(
            contractBalanceBefore + depositAmount
        )
        // 6. 验证合约内用户信息
        const userInfo = await advancedDeFi.userInfo(user.address)
        expect(userInfo.despositedAmount).to.equal(depositAmount) // 存款金额正确
        expect(userInfo.depositTime).to.be.gt(0) // 存款时间已记录
        expect(userInfo.earnedInterest).to.equal(0) // 初始无利息

        // 7. 验证总存款量
        const totalDeposits = await advancedDeFi.totalDeposits()
        expect(totalDeposits).to.equal(depositAmount)
    })
    it.only("解析存款事件并验证参数", async function () {
        const userDeFi = advancedDeFi.connect(user)
        const userToken = gameToken.connect(user)
        const defiAddress = await advancedDeFi.getAddress()

        // 授权并存款
        await userToken.approve(defiAddress, depositAmount)
        const depositTx = await userDeFi.deposit(depositAmount)
        await depositTx.wait()

        // 1. 基础验证：事件触发且参数正确
        await expect(depositTx)
            .to.emit(advancedDeFi, "Deposited")
            .withArgs(user.address, depositAmount, await getBlockTimestamp())

        // 2. 提取事件详情
        const logs = await advancedDeFi.queryFilter(
            "Deposited",
            depositTx.blockNumber
        )
        const depositedEvent = logs[0]
        console.log("==========", depositedEvent.args.user)

        // 3. 验证事件参数（详细检查）
        expect(depositedEvent.args.user).to.equal(user.address)
        expect(depositedEvent.args.amount).to.equal(depositAmount)
        const eventTimestamp = Number(depositedEvent.args.timestamp) // 显式转换
        // 验证时间戳（转换为Number后比较）
        expect(eventTimestamp).to.be.a("number").and.gt(0)
        // 4. 打印事件信息（调试用）
        console.log("\n=== 存款事件详情 ===")
        console.log("用户地址：", depositedEvent.args.user)
        console.log(
            "存款金额：",
            ethers.formatEther(depositedEvent.args.amount)
        )
        console.log(
            "时间戳：",
            new Date(eventTimestamp * 1000).toLocaleString()
        )
    })
    /**
     * 辅助函数：获取当前区块时间戳
     * @returns {number} 区块时间戳
     */
    async function getBlockTimestamp() {
        const blockNum = await ethers.provider.getBlockNumber()
        const block = await ethers.provider.getBlock(blockNum)
        return block.timestamp
    }
})
